package com.bestv.utils.common;

import org.apache.mahout.cf.taste.impl.common.FastByIDMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Map;

/**
 * 字符串编号映射到整数编号
 * User: Henry
 * Date: 14-5-8
 */
public class StringIdMap {
    private Logger logger = LoggerFactory.getLogger(getClass());

    private static final Charset UTF8_CHARSET = Charset.forName("UTF-8");
    private MessageDigest md5Digest;
    private FastByIDMap<String> longToString;

    public StringIdMap() {
        try {
            md5Digest = MessageDigest.getInstance("MD5");
            longToString = new FastByIDMap<String>(4096);
        } catch (NoSuchAlgorithmException e) {
            logger.error("No such algorithm.", e);
        }
    }

    private long hash(String value) {
        byte[] md5hash;
        synchronized (md5Digest) {
            md5hash = md5Digest.digest(value.getBytes(UTF8_CHARSET));
            md5Digest.reset();
        }

        long hash = 0L;
        for (int i=0; i<8; i++) {
            hash = hash << 8 | md5hash[i] & 0x00000000000000FFL;
        }
        return hash;
    }

    public long toLongId(String stringId) {
        return hash(stringId);
    }

    public String toStringId(long longId) {
        synchronized (longToString) {
            return longToString.get(longId);
        }
    }

    public void initialize(String[] stringIds) {
        for (String stringId : stringIds) {
            put(hash(stringId), stringId);
        }
    }

    public void initialize(ArrayList<Object[]> rs) {
        String[] stringIds = new String[rs.size()];
        for (int i=0; i<rs.size(); i++) {
            stringIds[i] = (String) rs.get(i)[0];
        }
        this.initialize(stringIds);
    }

    public void put(long longId, String stringId) {
        synchronized (longToString) {
            longToString.put(longId, stringId);
        }
    }

    public Object[][] list() {
        Object[][] data = new Object[longToString.size()][2];
        int i = 0;
        for (Map.Entry<Long, String> entry : longToString.entrySet()) {
            data[i][0] = entry.getKey();
            data[i][1] = entry.getValue();
            i++;
        }
        return data;
    }
}
